#ifndef CHOIXUNIFORME_H
#define CHOIXUNIFORME_H


class choixUniforme
{
    public:
        choixUniforme() {}
        virtual ~choixUniforme() {}

        float sampleUniform( gk::Vector& omega )
        {
            // on choisit un nb entre 0 et 1 pour r1 et r2
            const float r1= drand48();
            const float r2= drand48();

            float r= sqrtf(1.f - r2*r2);
            float phi= 2.f * M_PI * r1;

            omega= gk::Vector(
                cosf(phi) * r,
                sinf(phi) * r,
                r2);

            return 1.f / (2.f * M_PI); // probabilité d'avoir choisi cette direction
        }
        // generation d'une direction uniforme sur l'hemisphere,
        // renvoie la direction et la probabilite de l'avoir choisie
        // cf. global illumination compendium, eq 34



        // generation d'une direction proportionnelle a cos theta,
        // renvoie la direction et la probabilite de l'avoir choisie
        // cf. global illumination compendium, eq 35
        float sampleCosTheta( gk::Vector& omega )
        {
            // on choisit un nb entre 0 et 1 pour r1 et r2
            const float r1= drand48();
            const float r2= drand48();

            float r= sqrtf(1.f - r2);
            float phi= 2.f * M_PI * r1;
            float cos_theta= sqrtf(r2);

            omega= gk::Vector(
                cosf(phi) * r,
                sinf(phi) * r,
                cos_theta);

            return cos_theta / M_PI;
        }

        // eq 36
        float sample36( gk::Vector& omega, const unsigned int n)
        {
            // n = 0 -> eq 34
            // n = 1 -> eq 35

            const float r1= drand48();
            const float r2= drand48();

            float r= sqrtf(1.f - pow(r2, 2.f / (n + 1.f) ));
            float phi= 2.f * M_PI * r1;
            float cos_theta= pow(r2, 1.f / (n + 1.f));

            omega= gk::Vector(
                cosf(phi) * r,
                sinf(phi) * r,
                cos_theta);

            return (n+1.f) * pow(cos_theta,n) / (2.f * M_PI);
        }

        
        float sampleAmeliore( gk::Vector& omega, const unsigned int m, const double kd, const double ks)
        {
		
		const float r1= drand48();
		const float r2= drand48();
		
		float phi= 2.f * M_PI * r1;
		float cos_theta = pow(r2, 1/ (2*M_PI*kd + ks*(m+1.f)));
		float r = sqrtf(1.f - pow(r2, 2/ (2*M_PI*kd + ks*(m+1.f))));
		
		omega= gk::Vector(
			cosf(phi) * r,
			sinf(phi) * r,
			cos_theta);


            return   (kd + ks*(m+1.f) * pow(cos_theta,m) / (2.f * M_PI));
        }

        // evalue cos theta
        float fonction1( const gk::Vector& omega )
        {
            return gk::Dot( omega, gk::Vector(0.f, 0.f, 1.f) );

            // remarque, dans ce cas, cos theta = omega.z
        }


    protected:
    private:
};




#endif // CHOIXUNIFORME_H

